<?php

namespace wekcms\extend;

use OSS\OssClient;
use OSS\Core\OssException;

/**
 * 云储存类-天空蓝（https://gitee.com/wekyun/wekcms）作者
 */
class cloudDisk
{
    private static $instance;
    //基础配置
    public static $init_config = [];

    //最终类内部使用配置
    private static $config = [];
    //记录配置结构的测试配置
    private $cs_config = [
        'type' => 'oss',
        'client_config_oss' => [
            'accessKeyId ' => 'yourAccessKeyId',
            'accessKeySecret  ' => 'yourAccessKeySecret',
            'endpoint   ' => 'http://oss-cn-hangzhou.aliyuncs.com',// Endpoint以杭州为例，其它Region请按实际情况填写。
        ],
        'client_config_kodo' => [],
    ];

    //阿里云oss链接对象
    private static $ossClient = null;

    //信息提示
    public static function no_msg($msg, $title = false)
    {
        if ($title) {
            msg_no($msg, $title);
        } else {
            msg_no($msg);
        }
    }

    //防止使用new直接创建对象
    private function __construct()
    {
    }

    //防止使用clone克隆对象
    private function __clone()
    {
    }

    //获取当前类对象
    public static function getInstance()
    {
        //判断$instance是否是Singleton的对象，不是则创建
        if (!self::$instance instanceof self) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * @param array $config 优先基础配置，此配置init会覆盖基础配置
     */
    public static function init(array $config = [])
    {
        self::$config = array_merge(self::$init_config, $config);
        if (!self::$config) return self::no_msg(__FUNCTION__ . ': \n请设置配置参数\n');
        if (!in_array(self::$config['type'], ['oss', 'kodo'])) return self::no_msg(__FUNCTION__ . ': \n 配置type必须是：oss(阿里oss),kodo(七牛云储存kodo),其中之一 \n');
        switch (self::$config['type']) {
            case 'oss'://阿里云oss
                if (!isset(self::$config['client_config_oss']['accessKeyId']) || !isset(self::$config['client_config_oss']['accessKeySecret']) || !isset(self::$config['client_config_oss']['endpoint'])) return self::no_msg(__FUNCTION__ . ': \n 阿里云oss链接配置不可为空 \n');
                try {
                    // true为开启CNAME。CNAME是指将自定义域名绑定到存储空间上。
                    if (isset(self::$config['client_config_oss']['cname']) && 　self::$config['client_config_oss']['cname'] == true) {
                        self::$ossClient = new OssClient(self::$config['client_config_oss']['accessKeyId'], self::$config['client_config_oss']['accessKeySecret'], self::$config['client_config_oss']['endpoint'], true);
                    } else {
                        self::$ossClient = new OssClient(self::$config['client_config_oss']['accessKeyId'], self::$config['client_config_oss']['accessKeySecret'], self::$config['client_config_oss']['endpoint']);
                    }

                    // 设置Socket层传输数据的超时时间，单位秒，默认5184000秒。
                    self::$ossClient->setTimeout(3600);
                    // 设置建立连接的超时时间，单位秒，默认10秒。
                    self::$ossClient->setConnectTimeout(10);
                } catch (OssException $e) {
                    return self::no_msg(__FUNCTION__ . ': \n' . $e->getMessage() . '\n');
                }
                break;
            case 'kodo'://七牛云储存kodo

                break;
        }
        return self::getInstance();
    }

    /**
     * @param $bucket  参数
     * @return 选择存储空间(不存在就创建)
     */
    public function useBucketOss($config)
    {
        if (self::$ossClient == null) return self::no_msg('请先执行init初始化');
        /*
         * bucket               空间名称
         * oss_storage          储存类型
         * acl_type             访问权限
         * create               是否自动创建空间
         */
//        ['bucket' => 'imgzzhan99com', 'oss_storage' => 'oss3', 'acl_type' => 'public_read', 'create' => 1]
        try {
            if (is_string($config)) {//如果是字符串，就是选择了空间，不创建空间
                $configs['bucket'] = $config;
            } elseif (isset($config['create']) && $config['create']) {//如果是数组 并且开启自动创建，就组装创建数据
                $configs = $config;
                // 设置存储空间的存储类型为低频访问类型，默认是标准类型。
                // https://help.aliyun.com/document_detail/51374.htm?spm=a2c4g.11186623.2.5.fbec2a22yqc8Lc#concept-fcn-3xt-tdb
                $oss_storage = [
                    'oss1' => OssClient::OSS_STORAGE_ARCHIVE,//归档存储
                    'oss2' => OssClient::OSS_STORAGE_IA,//低频访问
                    'oss3' => OssClient::OSS_STORAGE_STANDARD,//标准存储
                    'oss4' => OssClient::OSS_STORAGE_COLDARCHIVE,//冷归档存储
                ];
                if (!isset($oss_storage[$configs['oss_storage']])) return self::no_msg('oss_storage储存类型不可为空');
                $options = array(
                    OssClient::OSS_STORAGE => $oss_storage[$configs['oss_storage']]
                );
                //空间权限类型：https://help.aliyun.com/document_detail/31843.htm?spm=a2c4g.11186623.2.4.fbec2a22pgVWdT#concept-fnt-4z1-5db
                $acl_type = [
                    'private' => OssClient::OSS_ACL_TYPE_PRIVATE,//私有
                    'public_read' => OssClient::OSS_ACL_TYPE_PUBLIC_READ,//公共读
                    'public_read_write' => OssClient::OSS_ACL_TYPE_PUBLIC_READ_WRITE,//公共读写
                ];
                if (!isset($acl_type[$configs['acl_type']])) return self::no_msg(__FUNCTION__ . ": \n" . '$config["acl_type"]错误：private：私有，public_read：公共读，public_read_write：公共读写', 'oss创建空间配置错误');
            }
            if (!isset($configs['bucket'])) return self::no_msg('请指定选择的:空间/bucket');
            //判断空间是否存在
            if (self::$ossClient->doesBucketExist($configs['bucket']) == true) {
                self::$config['client_config_oss']['bucket'] = $configs['bucket'];
                return self::getInstance();
            }
            if ($configs['create']) {//开启自动创建
                self::$ossClient->createBucket($configs['bucket'], $acl_type[$configs['acl_type']], $options);// 设置存储空间的权限为公共读，默认是私有读写。
            }
        } catch (OssException $e) {
            return self::no_msg(__FUNCTION__ . ": FAILED\n" . $e->getMessage() . "\n");
        }
        return self::getInstance();
    }


    /**
     * @param $config  参数
     * @return 选择文件夹
     */
    public function useFileOss($config)
    {
        if (self::$ossClient == null) return self::no_msg('请先执行init初始化');
        try {
            if (is_string($config)) {
                $configs['file_name'] = $config;

            } elseif ($config) {

            }
            $res = self::$ossClient->doesObjectExist(self::$config['client_config_oss']['bucket'], 'images/metouxiang.png');
            dd($res);

            if ($res) {
                self::$config['client_config_oss']['file_name'] = $configs['file_name'];
                return self::getInstance();
            }
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }

        return self::getInstance();
    }

    public function geFileListOss()
    {
        if (self::$ossClient == null) return self::no_msg('请先执行init初始化');
        $options = array(
            'delimiter' => '',
//            'prefix' => 'images',//指定前缀，用于指定文件夹
        );
        $listObjectInfo = self::$ossClient->listObjects(self::$config['client_config_oss']['bucket'], $options);
        $objectList = $listObjectInfo->getObjectList();

//        dd($objectList);
        $file_name_list = [];
        $file_md5_list = [];
        if (!empty($objectList)) {
            foreach ($objectList as $objectInfo) {
                //                print($objectInfo->getKey() . "\t" . $objectInfo->getSize() . "\t" . $objectInfo->getLastModified() . "\n");
                $file_name = $objectInfo->getKey();
                $file_name_last_str = substr($file_name, -1);
                if ($file_name_last_str == '/') {
                    $file_md5_list[md5($file_name)] = $file_name;
                    $file_name_list[] = $file_name;
                }

            }
        }
        $data = [
            'file_md5_list' => $file_md5_list,
            'file_name_list' => $file_name_list,
        ];
        return $data;
    }

    /**
     * Base64上传文件
     * @param string|array $images
     * @param string $model_path
     * @param string $model_type
     * @param string $upload_path 文件路径
     * @param bool $autoName
     * @return array
     */
    public function uploadImgBasse64Oss($images, $upload_path = '', $model_type = 'images')
    {
        if (self::$ossClient == null) return self::no_msg('请先执行init初始化');
        if (empty($images)) {
            return self::no_msg('文件列表不能为空');
        }
        $file_raw = [];
        $file_type = ['pjpeg', 'jpeg', 'jpg', 'gif', 'bmp', 'png', 'mov', '3gp', 'mp4', 'avi'];
        $preg_type = "image";
        $model_type = strtolower($model_type);
        if ($model_type == 'video') {
            $preg_type = $model_type;
        }

        //数组批量上传
        if (is_array($images) && count($images) > 0) {
            /*
             * $images 批量上传示例(值为一维单列或多列数组)
             * $images = [
             *      "base64/image1..........."
             *      "base64/image2..........."
             * ]
             */

            foreach ($images as $key => $value) {
                $value = trim($value);
                if (preg_match("/^(data:\s*$preg_type\/(\w+);base64,)/", $value, $result)) {
                    $type = strtolower($result[2]);
                    if (in_array($type, $file_type)) {
                        $file_raw[] = [
                            'raw' => base64_decode(str_replace($result[1], '', $value)), //文件流
                            'extension' => $type, //文件后缀
                            'index' => $key,
                        ];
                    } else {
                        return ['Code' => 0, 'Msg' => '文件类型错误'];
                    }
                } else {
                    return ['Code' => 0, 'Msg' => '文件base64格式不合法'];
                }
            }
        }

        //字符串单图上传
        if (is_string($images)) {
            /*
             * $images 上传单个示例，字符串
             * $images = "base64/image..........."
             */
            $images = trim($images);
            if (preg_match("/^(data:\s*$preg_type\/(\w+);base64,)/", $images, $result)) {
                $type = strtolower($result[2]);
                if (in_array($type, $file_type)) {
                    $file_raw[] = [
                        'raw' => base64_decode(str_replace($result[1], '', $images)), //文件流
                        'extension' => $type, //文件后缀
                        'index' => 0,
                    ];
                } else {
                    return self::no_msg('文件类型错误');
                }
            } else {
                $images = base64_encode($images);
                if (preg_match("/^(data:\s*$preg_type\/(\w+);base64,)/", $images, $result)) {
                    $type = strtolower($result[2]);
                    if (in_array($type, $file_type)) {
                        $file_raw[] = [
                            'raw' => base64_decode(str_replace($result[1], '', $images)), //文件流
                            'extension' => $type, //文件后缀
                            'index' => 0,
                        ];
                    } else {
                        return self::no_msg('文件类型错误');
                    }
                } else {
                    return self::no_msg('文件base64格式不合法');
                }
            }
        }


        $upload_img_url_list = [];
        try {
            if (!empty($file_raw)) {
                foreach ($file_raw as $value) {
                    $name = substr(md5(base64_encode($value['raw']) . base64_encode(time() . mt_rand(33, 126))), 8, 16);
                    if (substr($upload_path, -1) != '/') {
                        $upload_path .= '/';
                    }
                    $file_name = $upload_path . $name . "." . strtolower($value['extension']);
                    $getOssInfo = self::$ossClient->putObject(self::$config['client_config_oss']['bucket'], $file_name, $value['raw']);
                    $getOssPdfUrl = $getOssInfo['info']['url'];
                    $upload_img_url_list[$value['index']] = $getOssPdfUrl;
                }
            }
        } catch (OssException $e) {
            return self::no_msg(__FUNCTION__ . ": FAILED\n" . $e->getMessage() . "\n");
        }
        return $upload_img_url_list;
    }


}
